home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dr. Windows 3
/
dr win3.zip
/
dr win3
/
WINPROGS
/
WINSRC20.ZIP
/
WGENERAL.ASM
< prev
next >
Wrap
Assembly Source File
|
1990-09-29
|
13KB
|
516 lines
; Generic assembler routines that have very little at all
; to do with fractals.
;
;
; ---- 32-bit Multiply/Divide Routines (includes 16-bit emulation)
;
; multiply()
; divide()
;
.MODEL medium,c
.8086
.DATA
; ************************ Public variables *****************************
public overflow ; Mul, Div overflow flag: 0 means none
; arrays declared here, used elsewhere
; arrays not used simultaneously are deliberately overlapped
public prefix, suffix, dstack, decoderline ; for the Decoder
public strlocn, teststring, block ; used by the Encoder
public boxx, boxy, boxvalues ; zoom-box arrays
public olddacbox ; temporary DAC saves
public rlebuf ; Used ty the TARGA En/Decoder
; ************************* "Shared" array areas **************************
; Short forms used in subsequent comments:
; name........duration of use......................modules....................
; encoder "s"aving an image encoder.c
; decoder "r"estoring an image decoder.c, gifview.c
; zoom zoom box is visible zoom.c, video.asm
; vidswitch temp during video mode setting video.asm
; vidreset temp during video reset prompts.c, fractint.c, rotate.c, cmdfiles.c
; tgaview restore of tga image tgaview.c
; solidguess image gen with "g", not to disk calcfrac.c
; btm image gen with "b", not to disk calcfrac.c
block label byte ; encoder(266)
suffix dw 2048 dup(0) ; decoder(4k), vidswitch(256)
teststring label byte ; encoder(100)
dstack dw 2048 dup(0) ; decoder(4k), solidguess(4k), btm(2k)
; zoom(2k)
strlocn label word ; encoder(10k)
prefix label word ; decoder(8k), solidguess(6k)
olddacbox label byte ; vidreset(768)
boxx dw 2048 dup(0) ; zoom(4k), tgaview(4k)
boxy dw 2048 dup(0) ; zoom(4k)
boxvalues label byte ; zoom(2k)
decoderline db 2050 dup(0) ; decoder(2049), btm(2k)
rlebuf db 258 dup(0) ; f16.c(258) .tga save/restore?
; Internal Overflow flag
overflow dw 0 ; overflow flag
.CODE
; =======================================================
;
; 32-bit integer multiply routine with an 'n'-bit shift.
; Overflow condition returns 0x7fffh with overflow = 1;
;
; long x, y, z, multiply();
; int n;
;
; z = multiply(x,y,n)
;
; requires the presence of an external variable, 'cpu'.
; 'cpu' == 386 if a 386 is present.
.MODEL medium,c
.8086
.DATA
extrn cpu:word ; cpu flag: 88 = 8088/8086
; 186 = 80188/186
; 286 = 80286
; 386 = 80386/486
extrn fpu:word ; fpu flag: 0 = none
; 87 = 8087
; 287 = 80287
; 387 = 80387/(487)
temp dw 5 dup(0) ; temporary 64-bit result goes here
sign db 0 ; sign flag goes here
.CODE
multiply proc x:dword, y:dword, n:word
cmp cpu,386 ; go-fast time?
jne slowmultiply ; no. yawn...
.386 ; 386-specific code starts here
mov eax,x ; load X into EAX
imul y ; do the multiply
mov cx,n ; set up the shift
cmp cx,32 ; ugly klooge: check for 32-bit shift
jb short fastm1 ; < 32 bits: no problem
mov eax,edx ; >= 32 bits: manual shift
mov edx,0 ; ...
sub cx,32 ; ...
fastm1: shrd eax,edx,cl ; shift down 'n' bits
js fastm3
sar edx,cl
jne overmf
shld edx,eax,16
ret
fastm3: sar edx,cl
inc edx
jne overmf
shld edx,eax,16
ret
overmf:
mov ax,0ffffh ; overflow value
mov dx,07fffh ; overflow value
mov overflow,1 ; flag overflow
ret
.8086 ; 386-specific code ends here
slowmultiply: ; (sigh) time to do it the hard way...
push di
push si
mov ax,0
mov temp+4,ax ; first, zero out the (temporary)
mov temp+6,ax ; result
mov temp+8,ax
mov bx,word ptr x ; move X to SI:BX
mov si,word ptr x+2 ; ...
mov cx,word ptr y ; move Y to DI:CX
mov di,word ptr y+2 ; ...
mov sign,0 ; clear out the sign flag
cmp si,0 ; is X negative?
jge mults1 ; nope
not sign ; yup. flip signs
not bx ; ...
not si ; ...
stc ; ...
adc bx,ax ; ...
adc si,ax ; ...
mults1: cmp di,0 ; is DI:CX negative?
jge mults2 ; nope
not sign ; yup. flip signs
not cx ; ...
not di ; ...
stc ; ...
adc cx,ax ; ...
adc di,ax ; ...
mults2:
mov ax,bx ; perform BX x CX
mul cx ; ...
mov temp,ax ; results in lowest 32 bits
mov temp+2,dx ; ...
mov ax,bx ; perform BX x DI
mul di ; ...
add temp+2,ax ; results in middle 32 bits
adc temp+4,dx ; ...
jnc mults3 ; carry bit set?
inc word ptr temp+6 ; yup. overflow
mults3:
mov ax,si ; perform SI * CX
mul cx ; ...
add temp+2,ax ; results in middle 32 bits
adc temp+4,dx ; ...
jnc mults4 ; carry bit set?
inc word ptr temp+6 ; yup. overflow
mults4:
mov ax,si ; perform SI * DI
mul di ; ...
add temp+4,ax ; results in highest 32 bits
adc temp+6,dx ; ...
mov cx,n ; set up for the shift loop
cmp cx,24 ; shifting by three bytes or more?
jl multc1 ; nope. check for something else
sub cx,24 ; quick-shift 24 bits
mov ax,temp+3 ; load up the registers
mov dx,temp+5 ; ...
mov si,temp+7 ; ...
mov bx,0 ; ...
jmp short multc4 ; branch to common code
multc1: cmp cx,16 ; shifting by two bytes or more?
jl multc2 ; nope. check for something else
sub cx,16 ; quick-shift 16 bits
mov ax,temp+2 ; load up the registers
mov dx,temp+4 ; ...
mov si,temp+6 ; ...
mov bx,0 ; ...
jmp short multc4 ; branch to common code
multc2: cmp cx,8 ; shifting by one byte or more?
jl multc3 ; nope. check for something else
sub cx,8 ; quick-shift 8 bits
mov ax,temp+1 ; load up the registers
mov dx,temp+3 ; ...
mov si,temp+5 ; ...
mov bx,temp+7 ; ...
jmp short multc4 ; branch to common code
multc3: mov ax,temp ; load up the regs
mov dx,temp+2 ; ...
mov si,temp+4 ; ...
mov bx,temp+6 ; ...
multc4: cmp cx,0 ; done shifting?
je multc5 ; yup. bail out
multloop:
shr bx,1 ; shift down 1 bit, cascading
rcr si,1 ; ...
rcr dx,1 ; ...
rcr ax,1 ; ...
loop multloop ; try the next bit, if any
multc5:
cmp si,0 ; overflow time?
jne overm1 ; yup. Bail out.
cmp bx,0 ; overflow time?
jne overm1 ; yup. Bail out.
cmp dx,0 ; overflow time?
jl overm1 ; yup. Bail out.
cmp sign,0 ; should we negate the result?
je mults5 ; nope.
not ax ; yup. flip signs.
not dx ; ...
mov bx,0 ; ...
stc ; ...
adc ax,bx ; ...
adc dx,bx ; ...
mults5:
jmp multiplyreturn
overm1:
mov ax,0ffffh ; overflow value
mov dx,07fffh ; overflow value
mov overflow,1 ; flag overflow
multiplyreturn: ; that's all, folks!
pop si
pop di
ret
multiply endp
; =======================================================
;
; 32-bit integer divide routine with an 'n'-bit shift.
; Overflow condition returns 0x7fffh with overflow = 1;
;
; long x, y, z, divide();
; int n;
;
; z = divide(x,y,n); /* z = x / y; */
;
; requires the presence of an external variable, 'cpu'.
; 'cpu' == 386 if a 386 is present.
.8086
divide proc x:dword, y:dword, n:word
push di
push si
cmp cpu,386 ; go-fast time?
jne slowdivide ; no. yawn...
.386 ; 386-specific code starts here
mov edx,x ; load X into EDX (shifts to EDX:EAX)
mov ebx,y ; load Y into EBX
mov sign,0 ; clear out the sign flag
cmp edx,0 ; is X negative?
jge short divides1 ; nope
not sign ; yup. flip signs
neg edx ; ...
divides1:
cmp ebx,0 ; is Y negative?
jge short divides2 ; nope
not sign ; yup. flip signs
neg ebx ; ...
divides2:
mov eax,0 ; clear out the low-order bits
mov cx,32 ; set up the shift
sub cx,n ; (for large shift counts - faster)
fastd1: cmp cx,0 ; done shifting?
je fastd2 ; yup.
shr edx,1 ; shift one bit
rcr eax,1 ; ...
loop fastd1 ; and try again
fastd2:
cmp edx,ebx ; umm, will the divide blow out?
jae overd1 ; yup. better skip it.
div ebx ; do the divid